﻿using System;
using System.Collections.Generic;
using System.Linq;
using Go.Tools;

namespace Go.Model
{
    public class Position: IObservable
    {
        private Group _group;

        private List<Position> _neighborPositions;

        private Coordinate _coordinate;

        public Position(Coordinate aCoordinate)
        {
            this._group = null;
            _neighborPositions = new List<Position>();
            _coordinate = aCoordinate;
        }

        public bool isEmpty() {
            return this._group == null;
        }

        public void addStoneToGroup(Group aGroup) {
            if (!this.isEmpty())
                throw new System.ArgumentException("La posiocion no puede ser ocupada por una piedra");
            this._group = aGroup;
            aGroup.addPosition(this);
            foreach (Position aPosition in _neighborPositions)
                aPosition.addStoneAtNeighborPosition(aGroup);
        }

        //Se le avisa al grupo que una ficha del bando contrario fue insertada en su cercania
        private void addStoneAtNeighborPosition(Group aGroup)
        {
            if (( !this.isEmpty() ) && (!this.Group.isSameColor(aGroup)) )
                this.Group.calculateLiberty();
        }

        //Agrega a la aPosition como vecino de la instancia en caso de que ya no sea vecina
        public void addNeighborPosition(Position aPosition)
        {

            if (!(this._neighborPositions.Exists(item => (item == aPosition))))
            {
                this._neighborPositions.Add(aPosition);
                aPosition._neighborPositions.Add(this);
            }
        }

        public void posicionOcupada() {
            NotifyObservers(this);
        }

        //Devuelve true si la posiocion pasada debe ser vecina de esta posicion
        public bool itMustBeNeighbor(Position aPosition)
        {
            return ((Math.Abs(aPosition.X - this.X) == 1) && ((aPosition.Y - this.Y) == 0)) ||
                    (((aPosition.X - this.X) == 0) && (Math.Abs(aPosition.Y - this.Y) == 1));
        }



        // DEFINICIONES DE OPERADORES
        public static bool operator == (Position aPosition, Position otherPosition) {

            if ((Object)aPosition == null && (Object)otherPosition == null)
                return true;

            if ((Object)aPosition == null || (Object)otherPosition == null)
                return false;
            return (aPosition.X == otherPosition.X) && (aPosition.Y == otherPosition.Y);
        }

        public static bool operator != (Position aPosition, Position otherPosition) {
            return !(aPosition == otherPosition);
        }

       
        //Propiedades 
        public int Y
        {
            get { return _coordinate.y; }
        }
        public int X
        {
            get { return _coordinate.x; }
        }

        public List<Position> NeighborPositions
        {
            get { return _neighborPositions; }
        }

        public Coordinate Coordinate
        {
            get { return _coordinate; }
            set { _coordinate = value; }
        }

        public Group Group
        {
            get { return _group; }
            set { _group = value; }
        }



    }
}
